#ifndef XABSTRACTSYNTAXCOMPARE_H
#define XABSTRACTSYNTAXCOMPARE_H
#include <xscript/xitemboolean.h>
#include <xscript/xitemint32.h>
#include <xscript/xitemint64.h>
#include <xscript/xitemfloat.h>
#include <xscript/xitemdouble.h>
#include <xscript/xabstractsyntaxtree.h>

class XAbstractSyntaxTreeCompare : public XAbstractSyntaxTree {
  public:
    XAbstractSyntaxTreeCompare(XTokenPtr inputToken);
  public:
    template<class T>
    bool greate(T v, std::shared_ptr<XItem> item) {
        if (item->asInt32())
            return v > item->asInt32()->getValue();
        else if (item->asInt64())
            return v > item->asInt64()->getValue();
        else if (item->asFloat())
            return v > item->asFloat()->getValue();
        else if (item->asDouble())
            return v > item->asDouble()->getValue();
        return false;
    }

    template<class T>
    bool equal(T v, std::shared_ptr<XItem> item) {
        if (item->asInt32())
            return v == item->asInt32()->getValue();
        else if (item->asInt64())
            return v == item->asInt64()->getValue();
        else if (item->asFloat())
            return v == item->asFloat()->getValue();
        else if (item->asDouble())
            return v == item->asDouble()->getValue();
        return false;
    }

    template<class T>
    bool less(T v, std::shared_ptr<XItem> item) {
        return !(greate<T>(v, item) || equal<T>(v, item));
    }

    bool isFilled()const {return children.size() == 2;}
};

class XAbstractSyntaxTreeGreate : public XAbstractSyntaxTreeCompare {
  public:
    XAbstractSyntaxTreeGreate(XTokenPtr inputToken);
  public:
    XAbstractSyntaxTreeType getTreeType()const override {return XAbstractSyntaxTreeType_Greate;}
    bool invoke(std::shared_ptr<XVariableTable> table)override;
};

class XAbstractSyntaxTreeEqual : public XAbstractSyntaxTreeCompare {
  public:
    XAbstractSyntaxTreeEqual(XTokenPtr inputToken);
  public:
    XAbstractSyntaxTreeType getTreeType()const override {return XAbstractSyntaxTreeType_Equal;}
    bool invoke(std::shared_ptr<XVariableTable> table)override;
};

class XAbstractSyntaxTreeLess : public XAbstractSyntaxTreeCompare {
  public:
    XAbstractSyntaxTreeLess(XTokenPtr inputToken);
  public:
    XAbstractSyntaxTreeType getTreeType()const override {return XAbstractSyntaxTreeType_Less;}
    bool invoke(std::shared_ptr<XVariableTable> table)override;
};

class XAbstractSyntaxTreeGreateOrEqual : public XAbstractSyntaxTreeCompare {
  public:
    XAbstractSyntaxTreeGreateOrEqual(XTokenPtr inputToken);
  public:
    XAbstractSyntaxTreeType getTreeType()const override {return XAbstractSyntaxTreeType_GreateOrEqual;}
    bool invoke(std::shared_ptr<XVariableTable> table)override;
};

class XAbstractSyntaxTreeLessOrEqual : public XAbstractSyntaxTreeCompare {
  public:
    XAbstractSyntaxTreeLessOrEqual(XTokenPtr inputToken);
  public:
    XAbstractSyntaxTreeType getTreeType()const override {return XAbstractSyntaxTreeType_LessOrEqual;}
    bool invoke(std::shared_ptr<XVariableTable> table)override;
};

class XAbstractSyntaxTreeAnd : public XAbstractSyntaxTreeCompare {
  public:
    XAbstractSyntaxTreeAnd(XTokenPtr inputToken);
  public:
    XAbstractSyntaxTreeType getTreeType()const override {return XAbstractSyntaxTreeType_And;}
    bool invoke(std::shared_ptr<XVariableTable> table)override;
};

class XAbstractSyntaxTreeOr : public XAbstractSyntaxTreeCompare {
  public:
    XAbstractSyntaxTreeOr(XTokenPtr inputToken);
  public:
    XAbstractSyntaxTreeType getTreeType()const override {return XAbstractSyntaxTreeType_Or;}
    bool invoke(std::shared_ptr<XVariableTable> table)override;
};

class XAbstractSyntaxTreeNot : public XAbstractSyntaxTreeCompare {
  public:
    XAbstractSyntaxTreeNot(XTokenPtr inputToken);
  public:
    XAbstractSyntaxTreeType getTreeType()const override {return XAbstractSyntaxTreeType_Not;}
    bool invoke(std::shared_ptr<XVariableTable> table)override;
};

#endif // XABSTRACTSYNTAXCOMPARE_H
